package com.moyq5.spring.boot.app.register.server;

import java.io.Serializable;
import java.util.List;

import com.moyq5.spring.boot.app.register.AppGroup;
import com.moyq5.spring.boot.app.register.AppGroupStore;
import com.moyq5.spring.boot.app.register.AppInfo;
import com.moyq5.spring.boot.app.register.AppStatus;
import com.moyq5.spring.boot.app.register.AppStore;

/**
 * 应用信息处理
 * @author Moyq5
 * @date 2019年2月27日
 */
public class AppInfoExecutor {

	private AppInfoRegisterServerConfig config;
	
	/**
	 * 使用全局配置
	 * @see {@link AppInfoRegisterServerConfig}
	 */
	public AppInfoExecutor(){}
	
	/**
	 * 使用独立的配置
	 * @param config
	 */
	public AppInfoExecutor(AppInfoRegisterServerConfig config){
		this.config = config;
	}
	
	/**
	 * 添加或者更新应用信息
	 * @author Moyq5
	 * @date 2019年2月27日
	 * @param info
	 * @return 是否有变更
	 */
	public boolean update(AppInfo info) {
		boolean isChange = false;
		AppGroupStore groupStore = config().getGroupStore();
		AppGroup group = groupStore.get(info.getGroupId());
		if (null == group) {
			group = config().getCreator().createGroup(info.getGroupId());
			groupStore.add(group);
		}
		AppStore store = group.getStore();
		AppInfo exist = store.get(info.getAppId());
		if (null != exist) {
			exist.setOnTime(System.currentTimeMillis());// 有响应 表示在线
		} else {
			info.setStatus(AppStatus.ON);
			info.setOnTime(System.currentTimeMillis());
			store.add(info);
			isChange = true;
		}
		return isChange;
	}
	
	/**
	 * 检查所有应用组所有应用状态信息并通知远程任务
	 * @author Moyq5
	 * @date 2019年3月8日
	 */
	public void checkAndNoticeAll() {
		AppGroupStore store = config().getGroupStore();
		List<AppGroup> groups = store.list();
		groups.forEach(group -> {
			checkAndNotice(group);
		});
	}
	
	/**
	 * 检查指定应用组所有应用状态信息并通知远程应用
	 * @author Moyq5
	 * @date 2019年3月8日
	 * @param groupId
	 */
	public void checkAndNotice(Serializable groupId) {
		AppGroupStore store = config().getGroupStore();
		checkAndNotice(store.get(groupId));
	}
	
	/**
	 * 检查指定应用组所有应用状态信息并通知远程应用
	 * @author Moyq5
	 * @date 2019年2月27日
	 * @param group
	 */
	public void checkAndNotice(AppGroup group) {
		AppInfoNotifier notifier = group.getNotifier();
		AppStore store = group.getStore();
		int timeout = config().getTimeout();
		List<AppInfo> apps = store.list();
		int index = 0;
		int count = 0;
		for (AppInfo info: apps) {
			if (info.getOnTime() < System.currentTimeMillis() - timeout * 1000) {
				info.setStatus(AppStatus.OFF);
			}
			if (info.getStatus() == AppStatus.ON) {
				count++;
			}
		}
		for (AppInfo info: apps) {
			if (info.getStatus() == AppStatus.ON) {
				info.setOnCount(count);
				info.setOnIndex(index++);
			} else {
				info.setOnCount(0);
				info.setOnIndex(-1);
			}
			notifier.notice(info);
		}
	}
	
	private AppInfoRegisterServerConfig config() {
		return null != this.config ? this.config: AppInfoRegisterServerFactory.getConfig();
	}
}
